import ssl
import webbrowser
from typing import Optional

import requests
import urllib3
from urllib3.util.ssl_ import create_urllib3_context


# 专门用于发送请求
class CAAURLLoader:
    _SecurityContext: Optional[str] = None
    _content_type: Optional[str] = None
    _response_code: int = 0
    _response_msg: Optional[str] = None
    _last_redirect_url: Optional[str] = None

    def __init__(self, bypass_cert: bool = False):
        # 初始化Session对象用于自动管理Cookie
        self.session = requests.Session()

        # 设置自定义User-Agent
        self.session.headers.update({
            'User-Agent': 'CAA URL Loader Python',
            'Accept': 'application/json'
        })

        # 绕过证书验证（仅在bypass_cert为True时）
        if bypass_cert:
            print("\nBypassing certificates\n")
            self._disable_ssl_verification()

    def _disable_ssl_verification(self):
        """禁用SSL证书验证"""
        self.session.verify = False
        urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

        # 创建自定义SSL上下文
        ctx = create_urllib3_context()
        ctx.check_hostname = False
        ctx.verify_mode = ssl.CERT_NONE

        # 适配器用于HTTPS
        adapter = requests.adapters.HTTPAdapter(max_retries=3, ssl_context=ctx)
        self.session.mount('https://', adapter)

    def load_url(self, url: str, method: str = 'GET',
                 content_type: Optional[str] = None,
                 post_data: Optional[bytes] = None,
                 csrf: str = None) -> Optional[bytes]:
        """
        加载URL并获取响应

        :param url: 要请求的URL
        :param method: HTTP方法 (GET/POST/PATCH)
        :param content_type: 当method为POST时的内容类型
        :param post_data: POST/PATCH时发送的数据
        :return: 响应体内容 (bytes) 或 None
        """
        print("##CLIENT REQUEST 01")
        print("##------------------------------------------------------------")
        print(f"[{method}] {url}")

        try:
            # 处理PATCH方法
            headers = {}
            if method.upper() == 'PATCH':
                headers['X-HTTP-Method-Override'] = 'PATCH'
                print("  [HEADER] X-HTTP-Method-Override : PATCH")
                method = 'POST'

            # 添加SecurityContext头
            if self._SecurityContext:
                headers['SecurityContext'] = self._SecurityContext
                print(f"  [HEADER] SecurityContext : {self._SecurityContext}")

            # 设置请求参数
            kwargs = {
                'headers': headers,
                'allow_redirects': True,  # 自动处理重定向
                'timeout': 150000,  # 15秒超时
                'verify': False
            }

            # 处理POST/PATCH数据
            if post_data is not None and method in ('POST', 'PATCH'):
                # print(f"POST Data : {post_data.decode('utf-8', errors='replace')}")
                kwargs['data'] = post_data
                if content_type:
                    kwargs['headers']['Content-Type'] = content_type
                    print(f"Content-Type={content_type}")

            if csrf:
                kwargs['headers']['ENO_CSRF_TOKEN'] = csrf

            # 发送请求
            response = self.session.request(method, url, **kwargs)

            # 记录响应信息
            self._response_code = response.status_code
            self._response_msg = response.reason
            self._content_type = response.headers.get('Content-Type')

            print(f"\n##SERVER RESPONSE [{self._response_code}] {self._response_msg}")
            print("##--------------------")

            # 处理重定向
            if response.history:  # 如果有重定向历史
                self._last_redirect_url = response.url
                print(f"\nHas been redirected. Last Redirect URL : {self._last_redirect_url}")

            # 打印响应头
            print("\n#RESPONSE HEADER : ")
            print("#--------------------")
            print(f"HTTP/1.1 {self._response_code} {self._response_msg}")
            for k, v in response.headers.items():
                print(f"{k}: {v}")

            # 返回响应体
            if self._response_code in (200, 201):
                return response.content
            elif self._response_code == 204:  # No Content
                return None
            else:
                return response.content  # 错误响应也返回内容

        except requests.exceptions.RequestException as e:
            print(f"Request failed: {str(e)}")
            raise Exception(f"URL loading failed: {str(e)}")

    # 属性访问器

    def content_type(self) -> Optional[str]:
        return self._content_type

    def response_code(self) -> int:
        return self._response_code

    def response_message(self) -> Optional[str]:
        return self._response_msg

    def last_redirect_url(self) -> Optional[str]:
        return self._last_redirect_url

    # SecurityContext设置器
    def set_security_context(self, context: str):
        self._SecurityContext = context

    # 打开网页方法
    @staticmethod
    def open_web_page(url: str):
        try:
            webbrowser.open(url)
        except Exception as e:
            print(f"Failed to open web page: {str(e)}")
